from django.db.models import F
from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND
from rest_framework.viewsets import GenericViewSet, ModelViewSet

from community.models import Label, Article, Comment
from community.paginations import MyPagination
from community.serializers import LabelSerializer, ArticleSerializer, CommentSerializer, SonCommentSerializer
from config.dbs.RedisConfig import KEY_TEMPLATE_PAGE, EXPIRE_TIME


# Create your views here.
class LabelViewSet(GenericViewSet,ListModelMixin):
    queryset = Label.objects.all()
    serializer_class = LabelSerializer
    permission_classes = [IsAuthenticated]

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.filter(is_delete=False)
    serializer_class = ArticleSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = MyPagination

    def get_serializer_class(self):
        if self.action in ['comment']:
            return CommentSerializer
        else:
            return self.serializer_class

    def get_queryset(self):
        if self.action in ['list','retrieve','comment']:
            return self.queryset.filter(status=1)
        else:
            return self.queryset

    def create(self,request,*args, **kwargs):
        request.POST._mutable = True
        request.data['user'] = request.user.id
        return ModelViewSet.create(self,request,*args,**kwargs)

    def retrieve(self,request,*args, **kwargs):
        username = request.user.username
        cache = get_redis_connection(alias='verify_page_views')
        cache_key=KEY_TEMPLATE_PAGE % (username, kwargs['pk'])
        if not cache.get(cache_key):
            self.get_queryset().filter(id=kwargs['pk']).update(page_view=F('page_view')+1)
        cache.set(KEY_TEMPLATE_PAGE % (username, kwargs['pk']), kwargs['pk'], EXPIRE_TIME)
        return ModelViewSet.retrieve(self,request,*args,**kwargs)

    @action(methods=['get'],detail=True)
    def comment(self,request,pk):
        """
        得到指定文章的所有一级评论
        并且进行分页处理
        :param request:
        :param pk:
        :return:
        """
        # 得到指定的文章 管理器得到文章的所有评论 筛选出一级评论
        try:
            article = self.get_queryset().get(id=pk)
        except Article.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        comments = article.comment_set.filter(parent_comment__isnull=True)

        # 对筛选出的一级评论进行分页处理
        comments_page =self.paginate_queryset(comments)
        serializer = self.get_serializer(comments_page, many=True)
        return self.get_paginated_response(serializer.data)




class CommentViewSet(ModelViewSet):
    queryset = Comment.objects.filter(is_delete=False,article__is_delete=False,article__status=1)
    serializer_class = CommentSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = MyPagination

    def get_serializer_class(self):
        if self.action in ['retrieve']:
            return SonCommentSerializer
        else:
            return self.serializer_class

    def create(self,request,*args, **kwargs):
        request.POST._mutable = True
        request.data['user'] = request.user.id
        return ModelViewSet.create(self,request,*args,**kwargs)

    def retrieve(self,request,*args, **kwargs):
        """
        得到指定评论的子级评论
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # 得到指定评论
        try:
            # 在所有评论中找到指定id的评论
            comment = self.get_queryset().get(id=kwargs['pk'])
        except Article.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        # 管理器反向查找到的评论都是这个评论的子评论
        # 对子级评论进行分页处理
        page_son_comment=self.paginate_queryset(comment.parent_comment_set.all())
        serializer = self.get_serializer(page_son_comment, many=True)
        return self.get_paginated_response(serializer.data)
